using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Text.Json;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Linq;
using UwinEducation.Shared.Exceptions;
using UwinEducation.Shared.Models;

namespace UwinEducation.API.Middleware
{
    public class GlobalExceptionMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<GlobalExceptionMiddleware> _logger;

        public GlobalExceptionMiddleware(
            RequestDelegate next,
            ILogger<GlobalExceptionMiddleware> logger
        )
        {
            _next = next;
            _logger = logger;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            try
            {
                await _next(context);

                // 处理非成功状态码
                if (context.Response.StatusCode != StatusCodes.Status200OK)
                {
                    if (context.Response.ContentType == null)
                    {
                        switch (context.Response.StatusCode)
                        {
                            case 400:
                                throw new ArgumentException();
                            case 401:
                                throw new UnauthorizedAccessException();
                            case 403:
                                throw new Exception("403 禁止访问");
                            case 404:
                                throw new Exception("404 资源不存在");
                            default:
                                throw new Exception(context.Response.StatusCode.ToString());
                        }
                    }
                }
            }
            catch (BusinessException ex)
            {
                _logger.LogError(ex, "业务异常");
                await HandleBusinessExceptionAsync(context, ex);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理请求时发生未处理的异常");
                await HandleExceptionAsync(context, ex);
            }
        }

        private  async Task HandleExceptionAsync(HttpContext context, Exception exception)
        {
            if (!context.Response.HasStarted)
            {
                context.Response.ContentType = "application/json";
            }
            ApiResponse<object> response;

            switch (exception)
            {
                case ArgumentException:
                    context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    response = ApiResponse<object>.Error(exception.Message, 400);
                    break;
                case UnauthorizedAccessException:
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    response = ApiResponse<object>.Error("未授权访问", 401);
                    break;
                case KeyNotFoundException:
                    context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    response = ApiResponse<object>.Error("请求的资源不存在", 404);
                    break;
                case SecurityTokenExpiredException:
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    response = ApiResponse<object>.Error("Token已过期", 401);
                    break;
                default:
                    context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                    response = ApiResponse<object>.Error(
                        "服务器内部错误:" + exception.InnerException,
                        500
                    );
                    break;
            }

            // 只有在响应未开始的情况下才写入响应内容
            if (!context.Response.HasStarted)
            {
                await context.Response.WriteAsJsonAsync(response);
            }
            else
            {
                _logger.LogInformation("Cannot write error response because the response has already started.");
            }

            //var options = new JsonSerializerOptions
            //{
            //    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            //};

            //var jsonString = JsonSerializer.Serialize(response, options);

            ////var text = await new StreamReader(context.Response.Body).ReadToEndAsync();

            //await context.Response.WriteAsync(jsonString);
        }

        private static async Task HandleBusinessExceptionAsync(
            HttpContext context,
            BusinessException exception
        )
        {
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = (int)HttpStatusCode.BadRequest;

            //封装对象到ApiResponse
            var response = ApiResponse<object>.HandleBusinessException(
                 new
                 {
                     Code = exception.Code,
                     Messages = exception.Messages
                 },
                400
            );

            var options = new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            };
            var jsonString = JsonSerializer.Serialize(response, options);
            await context.Response.WriteAsync(jsonString);
        }
    }
}
